package com.lagou.sqlSession;

import com.lagou.config.BoundSql;
import com.lagou.pojo.Configuration;
import com.lagou.pojo.MappedStatement;
import com.lagou.utils.*;

import javax.sql.DataSource;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @author: jie.zhao
 * @create: 2021/01/31 18:22
 */
public class SimpleExecutor implements Executor {


    public <T> List<T> query(String statementId, Configuration configuration, Object... parames) throws SQLException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException, IntrospectionException, InstantiationException, InvocationTargetException {
        DataSource dataSource = configuration.getDataSource();
        Connection connection = dataSource.getConnection();
        List<T> list = new ArrayList<T>();
        MappedStatement mappedStatement = configuration.getSqlMapperMap().get(statementId);
        String sql = mappedStatement.getSql();
        BoundSql boundSql = BoundSqlUtil.getBoundSql(sql);

        PreparedStatement preparedStatement = connection.prepareStatement(boundSql.getSqlText());

        List<ParameterMapping> parameterMappingList = boundSql.getParameterMappingList();
        for (int i = 0; i < parameterMappingList.size(); i++) {
            Class<?> parameterClass = ClassUtil.getClassType(mappedStatement.getParameterType());
            ParameterMapping parameterMapping = parameterMappingList.get(i);
            String content = parameterMapping.getContent();
            Field field = parameterClass.getDeclaredField(content);
            field.setAccessible(true);
            Object o = field.get(parames[0]);
            preparedStatement.setObject(i + 1, o);
        }

        Class<?> resultTypeClass = ClassUtil.getClassType(mappedStatement.getResultType());
        Object o = resultTypeClass.newInstance();
        ResultSet resultSet = preparedStatement.executeQuery();
        while (resultSet.next()) {

            ResultSetMetaData metaData = resultSet.getMetaData();
            for (int i = 1; i <= metaData.getColumnCount(); i++) {
                String name = metaData.getColumnName(i);
                Object value = resultSet.getObject(name);
                PropertyDescriptor propertyDescriptor = new PropertyDescriptor(name,resultTypeClass);
                Method writeMethod = propertyDescriptor.getWriteMethod();
                writeMethod.invoke(o,value);
            }
            list.add((T) o);
        }

        return list;
    }





}
